Type GUI_v0_Main Extends GUI_Main

	Const UPDATE_FREQUENCY:Int = 60 'times per second.
	Const UPDATE_TIME:Int      = 1000 / UPDATE_FREQUENCY
	Const UPDATE_SCALE:Float   = 1000.0 / Float(UPDATE_TIME)

	Field applicationDir:String
	Field components:TList
	Field juke:Jukebox
	Field lib:Library
	Field running:Int
	Field componentsUpdate:TList
	Field sortUpdate:Byte
	Field componentsRender:TList
	Field sortRender:Byte

	Function compareUpdate:Int( o1:Object,o2:Object )
		Local c1:GUI_v0_MainComponent_Abstract = GUI_v0_MainComponent_Abstract(o1)
		Local c2:GUI_v0_MainComponent_Abstract = GUI_v0_MainComponent_Abstract(o2)
		If Not c1 Or Not c2 Then
			Return 0
		End If
		Local p1:Int = c1.GetUpdatePriority()
		Local p2:Int = c2.GetUpdatePriority()
		If p1 = p2 Then
			Return 0
		Else If p1 > p2 Then
			Return 1
		End If
		Return -1
	End Function

	Function compareRender:Int( o1:Object,o2:Object )
		Local c1:GUI_v0_MainComponent_Abstract = GUI_v0_MainComponent_Abstract(o1)
		Local c2:GUI_v0_MainComponent_Abstract = GUI_v0_MainComponent_Abstract(o2)
		If Not c1 Or Not c2 Then
			Return 0
		End If
		Local p1:Int = c1.GetRenderPriority()
		Local p2:Int = c2.GetRenderPriority()
		If p1 = p2 Then
			Return 0
		Else If p1 > p2 Then
			Return 1
		End If
		Return -1
	End Function

	Method New()
		components       = New TList
		componentsUpdate = New TList
		componentsRender = New TList		
		running          = True
		flagUpdatePriorityChange()
		flagRenderPriorityChange()
	End Method

	Method AddComponent(c:GUI_v0_MainComponent_Abstract)
		flagUpdatePriorityChange()
		flagRenderPriorityChange()
		If components.Contains(Object(c)) = False Then
			components.addLast(c)
		End If
	End Method
	
	Method RemoveComponent(c:GUI_v0_MainComponent_Abstract)
		flagUpdatePriorityChange()
		flagRenderPriorityChange()
		components.Remove(Object(c))
	End Method
	
	Method ClearObservers()
		components.Clear()
	End Method
	
	Method GetApplicationDir:String()
		Return applicationDir
	End Method
	
	Method GetJukebox:Jukebox()
		Return juke
	End Method
	
	Method GetLibrary:Library()
		Return lib
	End Method
	
	Method IsRunning:Int()
		Return running
	End Method
	
	Method Terminate()
		running = False
	End Method

	Method ResetGraphics()
		SetAlpha(1)
		SetBlend(ALPHABLEND)
		SetClsColor(0, 0, 0)
		SetColor(255, 255, 255)
		SetHandle(0, 0)
		SetImageFont(Null)
		SetLineWidth(1)
		SetOrigin(0, 0)
		SetTransform(0, 1, 1)
		SetViewport(0, 0, GraphicsWidth(), GraphicsHeight())
	End Method	

	Method run(applicationDir:String, juke:Jukebox, lib:Library) 
		' Start up...
		self.applicationDir = applicationDir
		self.juke           = juke
		self.lib            = lib
		
		'Graphics...
		SetGraphicsDriver(GLMax2DDriver(),GRAPHICS_BACKBUFFER|GRAPHICS_ALPHABUFFER|GRAPHICS_ACCUMBUFFER|GRAPHICS_DEPTHBUFFER|GRAPHICS_STENCILBUFFER)
		Local gfx:TGraphics=CreateGraphics(800, 600, 0, 60, 0)
		SetGraphics(gfx)
				
		'Input...
		Local pInput:GUI_PolledInput = GUI_PolledInput.GetInstance()
		
		' Initialize...
		Local c:Object
		For c = EachIn components
			GUI_v0_MainComponent_Abstract(c).Initialize(Self)
		Next
		c = Null
		' Main loop...
		Local dt:Int = 0
		Local et:Int = 0
		Local t:Int  = MilliSecs()
		Local tween:Float
		GCSetMode(2)
		GCCollect()
		While IsRunning()
			dt = MilliSecs() - t
			t  = MilliSecs()
			et:+dt
			' Update...			
			While et >= UPDATE_TIME And IsRunning()
				If sortUpdate = 1 Then
				    sortComponentsForUpdate()
				End If
				pInput.Poll()
				If pInput.KeyHit(KEY_ESCAPE) Or pInput.AppTerminate() Then
					Terminate()
				End If
				For c = EachIn componentsUpdate
					GUI_v0_MainComponent_Abstract(c).Update(Self)
				Next
				c = Null
				et:- UPDATE_TIME
				GCCollect()
			End While
			' Render...
			If sortRender = 1 Then
			    sortComponentsForRender()
			End If
			tween = Float(et) / UPDATE_TIME
			SetGraphics(gfx)
			ResetGraphics()
			Cls()
			For c = EachIn componentsRender
				GFX_TextureRender.BeginBackBuffer()
				ResetGraphics()
				GUI_v0_MainComponent_Abstract(c).Render(Self, tween)
				GFX_TextureRender.EndBackBuffer()
				GCCollect()
			Next
			c = Null
			Flip(1)
		End While
		componentsUpdate.Clear()
		flagUpdatePriorityChange()
		componentsRender.Clear()
		flagRenderPriorityChange()
		GCCollect()
		GCSetMode(1)
		' Uninitialize...
		For c = EachIn components
			GUI_v0_MainComponent_Abstract(c).Uninitialize(Self)
		Next
		c = Null
		' Close down...
		CloseGraphics(gfx)
		gfx                 = Null
		self.applicationDir = Null
		self.juke           = Null
		self.lib            = Null
	End Method
	
	Method flagUpdatePriorityChange()
		sortUpdate = 1
	End Method
	
	Method sortComponentsForUpdate()
		sortUpdate = 0
		componentsUpdate.Clear()
		componentsUpdate = components.Copy()
		componentsUpdate.Sort(False, Self.compareUpdate)
	End Method
	
	Method flagRenderPriorityChange()
		sortRender = 1
	End Method

	Method sortComponentsForRender()
		sortRender = 0
		componentsRender.Clear()
		componentsRender = components.Copy()
		componentsRender.Sort(True, Self.compareRender)
	End Method

End Type
